home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
eulisp
/
feel-075.lha
/
feel0.75
/
Src
/
format.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-18
|
11KB
|
523 lines
/* ******************************************************************** */
/* format.c Copyright (C) Codemist and University of Bath 1989 */
/* */
/* Formatted IO */
/* ******************************************************************** */
/*
* Change Log:
* Version 1, June 1990
* $Id: format.c,v 1.6 1992/04/27 21:56:08 pab Exp $
*
* $Log: format.c,v $
* Revision 1.6 1992/04/27 21:56:08 pab
* corrected format
* ,
*
* Revision 1.5 1992/01/09 22:28:50 pab
* Fixed for low tag ints
*
* Revision 1.4 1992/01/05 22:48:03 pab
* Minor bug fixes, plus BSD version
*
* Revision 1.3 1991/12/22 15:14:04 pab
* Xmas revision
*
* Revision 1.2 1991/09/11 12:07:11 pab
* 11/9/91 First Alpha release of modified system
*
* Revision 1.1 1991/08/12 16:49:35 pab
* Initial revision
*
* Revision 1.9 1991/02/13 18:19:31 kjp
* Altered format NOT to call allocate string.
*
* Revision 1.8 1990/12/18 14:32:09 jpff
* Binary Format fix
*
* Revision 1.7 90/12/18 14:27:28 jpff
* typo
*
* Revision 1.6 90/12/18 14:25:34 jpff
* Improved e f and g formats, implemented b formay
*
* Revision 1.5 90/12/18 14:06:47 jpff
* More on format
*
* Revision 1.4 90/12/18 13:17:28 jpff
* Extra formats
*
* Revision 1.3 90/12/18 12:27:29 jpff
* Added formats, and case labels for unimplemented stuff
*
* Revision 1.2 90/11/23 16:36:05 is
* Added Id and Log fields
* Added ~u (for uniq) format specifier, which prints out nil or the hex
* address of the object
*
*/
#include <string.h>
#include <stdio.h>
#include "funcalls.h"
#include "defs.h"
#include "structs.h"
#include "error.h"
#include "global.h"
#include "modboot.h"
#include "symboot.h"
#include "ngenerics.h"
#include "sio.h"
/*
* O..
*/
LispObject format_to_string(LispObject *stacktop,
LispObject format,LispObject list)
{
char *walker = stringof(format);
int index;
/* Hack using socket writer... */
BUFFER_PTR() = 0;
while (TRUE) {
index = 0;
while (*walker != '~' && *walker != '\0') {
*(BUFFER()) = *walker;
++walker; ++index; ++(BUFFER_PTR());
}
if (*walker == '\0') {
*(BUFFER()) = '\0';
return((LispObject)
allocate_string(stacktop,BUFFER_START(),strlen(BUFFER_START())));
}
++walker;
switch (*walker) {
case '\0':
CallError(stacktop,"format: ~ at end of string",format,NONCONTINUABLE);
break;
case '~':
*(BUFFER()) = '~';
++(BUFFER_PTR());
break;
case '%':
*(BUFFER()) = '\n';
++(BUFFER_PTR());
break;
case 't':
*(BUFFER()) = '\t';
++(BUFFER_PTR());
break;
case '|':
*(BUFFER()) = '\f';
++(BUFFER_PTR());
break;
case 'a':
if (is_cons(list)) {
if (is_string(CAR(list))) {
strcpy(BUFFER(),stringof(CAR(list)));
BUFFER_PTR() += strlen(stringof(CAR(list)));
}
else {
write_object(stacktop,CAR(list));
}
list = CDR(list);
}
else {
write_object(stacktop,nil);
}
break;
default:
*(BUFFER()) = *walker;
++(BUFFER_PTR());
break;
}
++walker;
}
return(nil);
}
/* Lisp.. */
#define FORMAT_BUFFER_SIZE (512)
EUFUN_3( Fn_format, str, format, list)
{
extern LispObject Gf_generic_prin(LispObject*);
extern LispObject Gf_generic_write(LispObject*);
LispObject ostream,pstring;
char buffer[FORMAT_BUFFER_SIZE];
char *walker;
int index;
if (!is_string(format))
CallError(stacktop,"format: not a string",format,NONCONTINUABLE);
if (str == nil) return(format_to_string(stacktop,format,list));
if (str == lisptrue) ostream = StdOut;
else ostream = str;
if (!is_stream(ostream))
CallError(stacktop,"format: not a stream",ostream,NONCONTINUABLE);
if (!is_string(format))
CallError(stacktop,"format: not a string",format,NONCONTINUABLE);
/* Copy the string into the buffer until a tilda... */
walker = stringof(format);
while (TRUE) {
index = 0;
while (*walker != '~' && *walker != '\0') {
if (index >= FORMAT_BUFFER_SIZE)
CallError(stacktop,
"format: out of buffer space",format,NONCONTINUABLE);
buffer[index] = *walker;
walker += 1; ++index;
}
buffer[index] = '\0';
/* Output this string... */
/*
STACK_TMP(ostream);
pstring = (LispObject) allocate_string(stacktop,buffer,index);
UNSTACK_TMP(ostream);
STACK_TMP(ostream);
EUCALL_2(Gf_generic_prin,pstring,ostream);
UNSTACK_TMP(ostream);
*/
/* Cheat... */
fprintf(ostream->STREAM.handle,"%s",buffer);
if (*walker == '\0') {
/* All done... */
return(nil);
}
/* We have a tilde modifier... */
++walker;
list = ARG_2(stackbase);
format = ARG_1(stackbase);
switch (*walker) {
case '\0':
CallError(stacktop,"format: ~ at end of string",format,NONCONTINUABLE);
break;
case '~':
fprintf(ostream->STREAM.handle,"~");
break;
case '%':
fprintf(ostream->STREAM.handle,"\n");
break;
case 't':
fprintf(ostream->STREAM.handle,"\t");
break;
case '|':
fprintf(ostream->STREAM.handle,"\f");
break;
case 'a':
{
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
STACK_TMP(ostream);
EUCALL_2(Gf_generic_prin,obj,ostream);
UNSTACK_TMP(ostream);
break;
}
case 's':
{
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
STACK_TMP(ostream);
EUCALL_2(Gf_generic_write,obj,ostream);
UNSTACK_TMP(ostream);
break;
}
case 'u':
{
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
fprintf(ostream->STREAM.handle,(obj==nil)?"nil":"#x%x",obj);
break;
}
case 'c': /* Print a character */
{
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
if (is_char(obj))
fprintf(ostream->STREAM.handle,"%c",obj->CHAR.code);
else
fprintf(ostream->STREAM.handle,"?");
break;
}
case 'd': /* Print in decimal */
{
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
if (is_fixnum(obj))
fprintf(ostream->STREAM.handle,"%d",intval(obj));
else
fprintf(ostream->STREAM.handle,"<not-integer>");
break;
}
case 'o': /* Print in octal */
{
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
if (is_fixnum(obj))
fprintf(ostream->STREAM.handle,"%o",intval(obj));
else
fprintf(ostream->STREAM.handle,"<not-integer>");
break;
}
case 'x':
{
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
if (is_fixnum(obj))
fprintf(ostream->STREAM.handle,"%x",intval(obj));
else
fprintf(ostream->STREAM.handle,"<not-integer>");
break;
}
case 'e': /* Print in fpt E format */
{ int n = 0, m = 0;
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
while (isdigit(*++walker)) m = 10 * m + *walker - '0';
if (*walker == '.') {
while (isdigit(*++walker)) n = 10 * n + *walker - '0';
if (is_float(obj))
fprintf(ostream->STREAM.handle,"%*.*E",m-n,n,obj->FLOAT.fvalue);
else
fprintf(ostream->STREAM.handle,"<not-floatinginteger>");
walker--;
}
else {
if (is_float(obj))
fprintf(ostream->STREAM.handle,"%E",(obj)->FLOAT.fvalue);
else
fprintf(ostream->STREAM.handle,"<not-floatinginteger>");
walker--;
}
break;
}
case 'f': /* Print in fpt F format */
{ int n = 0, m = 0;
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
while (isdigit(*++walker)) m = 10 * m + *walker - '0';
if (*walker == '.') {
while (isdigit(*++walker)) n = 10 * n + *walker - '0';
if (is_float(obj))
fprintf(ostream->STREAM.handle,"%*.*F",m-n,n,obj->FLOAT.fvalue);
else
fprintf(ostream->STREAM.handle,"<not-floating>");
walker--;
}
else {
walker--;
if (is_float(obj))
fprintf(ostream->STREAM.handle,"%F",(obj)->FLOAT.fvalue);
else
fprintf(ostream->STREAM.handle,"<not-floating>");
}
break;
}
case 'g': /* Print in fpt G format */
{ int n = 0, m = 0;
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
while (isdigit(*++walker)) m = 10 * m + *walker - '0';
if (*walker == '.') {
while (isdigit(*++walker)) n = 10 * n + *walker - '0';
if (is_float(obj))
fprintf(ostream->STREAM.handle,"%*.*G",m-n,n,obj->FLOAT.fvalue);
else
fprintf(ostream->STREAM.handle,"<not-floating>");
walker--;
}
else {
if (is_float(obj))
fprintf(ostream->STREAM.handle,"%G",obj->FLOAT.fvalue);
else
fprintf(ostream->STREAM.handle,"<not-floating>");
walker--;
}
break;
}
case 'b': /* Print in binary */
{
LispObject obj;
if (is_cons(list)) {
obj = CAR(list);
ARG_2(stackbase) = list = CDR(list);
}
else obj = nil;
if (is_fixnum(obj)) {
char bb[100]; /* WARNING: limit here */
char *p = bb;
int i = 0;
int n = intval(obj);
while (n!=0) {
*p++ = (n&1) + '0';
i++;
n >>=1;
}
for (p--; i>0; p--, i--) fprintf(ostream->STREAM.handle,"%c",*p);
}
else
fprintf(ostream->STREAM.handle,"<not-integer>");
break;
}
case 'p': /* Prettyprint */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '&':
default:
fprintf(ostream->STREAM.handle,"%c",*walker);
}
/* Lose character... */
++walker;
/* Now, do it again... */
}
return(nil);
}
EUFUN_CLOSE
/*
* Module initialisation...
*/
#define FORMATTED_IO_ENTRIES 1
MODULE Module_formatted_io;
LispObject Module_formatted_io_values[FORMATTED_IO_ENTRIES];
void initialise_formatted_io(LispObject *stacktop)
{
BUFFER_START() = (char *)malloc(SOCKET_BUFFER_SIZE);
open_module(stacktop,
&Module_formatted_io,
Module_formatted_io_values,
"formatted-io",
FORMATTED_IO_ENTRIES);
(void) make_module_function(stacktop,"format",Fn_format,-3);
close_module();
}